package ai.people.netmon.auth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.*;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity
@Order(-1)
@Import(SecurityProblemSupport.class)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private SecurityProblemSupport securityProblemSupport;


    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/login", "/userlogout", "/checkToken",
                "/refreshToken", "/logout", "/auth/oauth/token","/oauth/authorize");

    }

    /**
     * 身份验证管理器
     *
     * @return {@link AuthenticationManager}
     * @throws Exception 异常
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        AuthenticationManager manager = super.authenticationManagerBean();
        return manager;
    }

    /**
     * 密码编码器
     *
     * @return {@link PasswordEncoder}
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        var idForDefault = "bcrypt";
        Map<String, PasswordEncoder> passwordEncoderMap = new HashMap<>();
        passwordEncoderMap.put(idForDefault, new BCryptPasswordEncoder());
        // 兼容旧系统使用的MD5加密算法、框架在截取数据库中密码前缀时返回null 获取以null为key的MD5密码编码器处理数据库中MD5的加密旧密码
        passwordEncoderMap.put(null, new MessageDigestPasswordEncoder("MD5"));
        passwordEncoderMap.put("ldap", new LdapShaPasswordEncoder());
        passwordEncoderMap.put("MD4", new Md4PasswordEncoder());
        passwordEncoderMap.put("noop", NoOpPasswordEncoder.getInstance());
        passwordEncoderMap.put("pbkdf2", new Pbkdf2PasswordEncoder());
        passwordEncoderMap.put("scrypt", new SCryptPasswordEncoder());
        passwordEncoderMap.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
        passwordEncoderMap.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
        passwordEncoderMap.put("sha256", new StandardPasswordEncoder());
        passwordEncoderMap.put("argon2", new Argon2PasswordEncoder());
        passwordEncoderMap.put("MD5", new MessageDigestPasswordEncoder("MD5"));
        return new DelegatingPasswordEncoder(idForDefault, passwordEncoderMap);
    }



    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .exceptionHandling(exp ->
                        exp.authenticationEntryPoint(securityProblemSupport)
                                .accessDeniedHandler(securityProblemSupport))
                .httpBasic().and()
                .formLogin()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().anyRequest().authenticated();

    }


    //@Override
    //protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //    auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    //}
}
